package com.wyz.saas.common.base

import android.content.Intent
import android.os.Build
import android.view.KeyEvent
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import com.atom.module.mvvm.base.IViewModel
import com.wyz.saas.api.common.FragmentApi

abstract class AbstractApiContainerActivity<V : ViewDataBinding, VM : AbstractApiViewModel<*>> : AbstractApiActivity<V, VM>(), FragmentApi {

    private val EXTRA_FRAGMENT_CLASS_NAME = "activity.fragment.classname"
    private val EXTRA_REQUEST_PERMISSIONS = "activity.request.permissions"

    protected abstract fun getFrameLayoutId(): Int

    override fun loadFragment(
        fragment: Fragment,
        addToBackStack: Boolean
    ) {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction =
            fragmentManager.beginTransaction()
        val fragmentById =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragmentById == null) {
            fragmentTransaction.add(getFrameLayoutId(), fragment, fragment.javaClass.name)
        } else {
            fragmentTransaction.replace(getFrameLayoutId(), fragment, fragment.javaClass.name)
        }
        if (addToBackStack) {
            fragmentTransaction.addToBackStack(fragment.javaClass.name)
        }
        fragmentTransaction.commit()
    }

    override fun changeFragment(
        newFragment: Fragment?,
        newClass: Class<out Fragment>,
        oldFragment: Fragment?
    ): Fragment {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()
        oldFragment?.also { fragmentTransaction.detach(it) } // 从界面移除，但是还在Fragment的缓存空间中
        val result = newFragment
            ?.let {
                fragmentTransaction.attach(it)
                it
            } // 从FragmentManger的缓存空间中重新加载到界面中
            ?: let {
                val fragment = Fragment.instantiate(getActivity(), newClass.name, null)
                fragmentTransaction.add(getFrameLayoutId(), fragment, fragment.javaClass.name)
                fragment
            }
        fragmentTransaction.commit()  // 提交事务
        return result
    }


    override fun onBackPressed() {
        val fragmentManager = supportFragmentManager
        var fragment = fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnBackPressedListener) {
            if (fragment.onBackPressed()) {
                return
            }
        }
        super.onBackPressed()
        fragment = fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment == null) {
            finish()
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment = fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnKeyPressedListener) {
            if (fragment.onKeyDown(keyCode, event)) {
                return true
            }
        }
        if (fragment is FragmentApi.OnMenuPressedListener) {
            if (keyCode == KeyEvent.KEYCODE_MENU) {
                if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ECLAIR) {
                    event.startTracking()
                } else {
                    fragment.onMenuPressed()
                }
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnKeyPressedListener) {
            if (fragment.onKeyLongPress(keyCode, event)) {
                return true
            }
        }
        return super.onKeyLongPress(keyCode, event)
    }

    override fun onKeyMultiple(
        keyCode: Int,
        count: Int,
        event: KeyEvent?
    ): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnKeyPressedListener) {
            if (fragment.onKeyMultiple(keyCode, count, event)) {
                return true
            }
        }
        return super.onKeyMultiple(keyCode, count, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnKeyPressedListener) {
            if (fragment.onKeyUp(keyCode, event)) {
                return true
            }
        }
        if (fragment is FragmentApi.OnMenuPressedListener) {
            if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ECLAIR) {
                if (keyCode == KeyEvent.KEYCODE_MENU && event.isTracking && !event.isCanceled) {
                    fragment.onMenuPressed()
                    return true
                }
            }
        }
        return super.onKeyUp(keyCode, event)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val fragmentManager = supportFragmentManager
        var fragment =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnNewIntentListener) {
            if (fragment.onNewIntent(intent)) {
                return
            }
        }
        val extra =
            intent.getStringArrayExtra(EXTRA_REQUEST_PERMISSIONS)
        val classname = intent.getStringExtra(EXTRA_FRAGMENT_CLASS_NAME)
        if (classname != null) {
            try {
                val clazz = classLoader.loadClass(classname)
                fragment = clazz.newInstance() as Fragment
                fragment.arguments = intent.extras
                if (fragment is FragmentApi.OnNewIntentListener) {
                    fragment.onNewIntent(intent)
                }
                loadFragment(fragment, true)
            } catch (e: Exception) {
                reportException(e)
            }
        }
    }

    override fun finish() {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(getFrameLayoutId())
        if (fragment is FragmentApi.OnFinishListener) {
            if (!fragment.onFinish()) {
                return
            }
        }
        super.finish()
    }
}